/*******************************************************************************
 *	                           oled spi.c
 *******************************************************************************/
#include "bsp.h"

#define SPIX SPI1
#define ISR_IRQn SPI1_IRQn

/*****************************************************************************
 * @brief   hal init.
 * @param   none
 * @return  none
 * @ Pass/ Fail criteria: none
 *****************************************************************************/
void ext_spi_init(void)
{
	SPI_Config_T cfg;
	intx_alloc();

	// 开启时钟
	intx_disable();

	RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SPI1);
	RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_SPI1);
	RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_SPI1);

	intx_enable();

	// SPI 配置
	cfg.direction = SPI_DIRECTION_2LINES_FULLDUPLEX;
	cfg.baudrateDiv = SPI_BAUDRATE_DIV_64;
	cfg.mode = SPI_MODE_MASTER;
	cfg.length = SPI_DATA_LENGTH_8B;
	cfg.firstBit = SPI_FIRSTBIT_MSB;
	cfg.nss = SPI_NSS_SOFT;
	cfg.polarity = SPI_CLKPOL_LOW;
	cfg.phase = SPI_CLKPHA_1EDGE;
	cfg.crcPolynomial = 0;

	SPI_Config(SPIX, &cfg);

	SPIX->CTRL1_B.SPIEN = 1;
}

/*****************************************************************************
 * @brief   cs ctr.
 * @param   none
 * @return  none
 * @ Pass/ Fail criteria: none
 *****************************************************************************/
void ext_spi_cs(uint8_t st)
{
	if (st)
	{
	}
	else
	{
	}
}

/*****************************************************************************
 * @brief   spi speed.
 *****************************************************************************/
void ext_spi_high_speed(void)
{
}

/*****************************************************************************
 * @brief   spi speed.
 *****************************************************************************/
void ext_spi_low_speed(void)
{
}

/*****************************************************************************
 * @brief   spi delay.
 *****************************************************************************/
#define spi_read_delay() NOP4()
#define is_spi_rx_ready() SPIX->STS_B.RXBNEFLG
#define spi_rx_reset()                     \
	while (is_spi_rx_ready())              \
	{                                      \
		volatile uint32_t rd = SPIX->DATA; \
	}
#define is_spi_busy() SPIX->STS_B.BSYFLG
#define spi_send(dat) SPIX->DATA = dat
#define is_spi_tx_full() (SPIX->STS_B.TXBEFLG == 0)
#define is_spi_tx_empty() SPIX->STS_B.TXBEFLG
#define spi_read() SPIX->DATA

/*****************************************************************************
 * @brief   spi data read.
 *****************************************************************************/
uint8_t ext_spi_rb(void)
{
	spi_rx_reset();

	// send data
	spi_send(0xFF);
	spi_read_delay();

	// wait for trans complete
	while (!is_spi_rx_ready())
		;

	// read data
	return (spi_read());
}

void ext_spi_wb(uint8_t dataW)
{
	volatile uint8_t rb;

	spi_rx_reset();

	// send data
	spi_send(dataW);
	spi_read_delay();

	// wait for trans complete
	while (!is_spi_rx_ready())
		;

	// read data
	rb = spi_read();
}

/*****************************************************************************
 * @brief   spi data read.
 *****************************************************************************/
uint8_t ext_spi_rw(uint8_t dataW)
{
	spi_rx_reset();

	// send data
	spi_send(dataW);
	spi_read_delay();

	// wait for trans complete
	while (!is_spi_rx_ready())
		;

	// read data
	return (spi_read());
}

/*****************************************************************************
 * @brief   spi data write.
 *****************************************************************************/
uint8_t ext_spi_write(const uint8_t *dataw, uint32_t Len)
{
	while (Len--)
	{
		// send data
		spi_send(*dataw++);

		spi_read_delay();

		while (is_spi_tx_full())
		{
		}
	}

	spi_read_delay();

	// wait for trans complete
	while (is_spi_busy() || !is_spi_tx_empty())
	{
	}

	spi_rx_reset();

	return (0);
}

/*****************************************************************************
 * @brief   spi data read.
 *****************************************************************************/
uint8_t ext_spi_read(uint8_t *datar, uint32_t Len)
{
	uint32_t rcnt = 0;

	spi_rx_reset();

	while (Len--)
	{
		// send data
		spi_send(0xFF);

		spi_read_delay();

		while (!is_spi_rx_ready())
		{
		}

		datar[rcnt++] = spi_read();
	}

	return 0;
}
